package com.secsbrain.development.biz.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.plugins.Page;
import com.secsbrain.common.ResponseVo;
import com.secsbrain.deploy.client.constant.EnumDefinition.BuildStatus;
import com.secsbrain.deploy.client.iface.DeployService;
import com.secsbrain.deploy.client.model.BatchBuildParam;
import com.secsbrain.deploy.client.model.BatchBuildResult;
import com.secsbrain.deploy.client.model.BuildParam;
import com.secsbrain.deploy.client.model.BuildRecord;
import com.secsbrain.development.biz.BuilderService;
import com.secsbrain.development.biz.IDeployApprovalService;
import com.secsbrain.development.biz.IDeployPlanRecordService;
import com.secsbrain.development.biz.IDeployPlanService;
import com.secsbrain.development.biz.IDeployPlanTestService;
import com.secsbrain.development.biz.IProjectAppService;
import com.secsbrain.development.biz.constant.TaskStatus;
import com.secsbrain.development.biz.exception.BizMessageException;
import com.secsbrain.development.dal.model.DeployApproval;
import com.secsbrain.development.dal.model.DeployPlan;
import com.secsbrain.development.dal.model.DeployPlanRecord;
import com.secsbrain.development.dal.model.DeployPlanTest;
import com.secsbrain.development.dal.model.ProjectApp;
import com.secsbrain.development.web.dto.BuildSnapshotDTO;
import com.secsbrain.development.web.dto.CommandContext;
import com.secsbrain.development.web.dto.ProjectTaskDTO;
import com.secsbrain.development.web.dto.SingleTaskDTO;

import com.secsbrain.development.biz.constant.EnumDefinition;
import com.secsbrain.sso.core.SsoHelper;
import com.secsbrain.sso.model.dto.system.UserDetailDTO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
@Transactional
public class BuildServiceImpl implements BuilderService {
	
    private static final Logger LOGGER = LoggerFactory.getLogger(BuilderService.class);
    
    @Autowired
	DeployService deployService;
    
    @Autowired
    IDeployApprovalService deployApprovalService;
    
    @Autowired
    IProjectAppService projectAppService;
    
    @Autowired
    IDeployPlanService deployPlanService;
    
    @Autowired
    IDeployPlanRecordService deployPlanRecordService;
    
    @Autowired
    IDeployPlanTestService deployPlanTestService;
    
    private List<BuildSnapshotDTO> queryPlanBuildRecord(Long projectId, String envId){
		DeployPlanRecord deployPlanRecordParam=new DeployPlanRecord();
		deployPlanRecordParam.setPlanId(projectId);
		List<DeployPlanRecord> list=deployPlanRecordService.selectList(deployPlanRecordParam);
		List<BuildSnapshotDTO> buildSnapshotDTOs=new ArrayList<BuildSnapshotDTO>();

		for(DeployPlanRecord deployPlanRecord:list){
			BuildSnapshotDTO buildSnapshotDTO=new BuildSnapshotDTO();
			buildSnapshotDTO.setId(deployPlanRecord.getId());
			buildSnapshotDTO.setCreatedTime(deployPlanRecord.getCreateTime());
			buildSnapshotDTO.setExecutorName(deployPlanRecord.getCreateName());
			
			ResponseVo<List<BuildRecord>> buildRecordVo=deployService.queryBuildListByBatchId(deployPlanRecord.getId(), envId);
			if(!buildRecordVo.isSuccess()|| CollectionUtils.isEmpty(buildRecordVo.getData())){
				LOGGER.error("批量查询构建记录失败："+buildRecordVo.getMsg());
			}else{
				List<BuildSnapshotDTO> records=new ArrayList<>();
				
				for(BuildRecord buildRecord: buildRecordVo.getData()){
					if(BuildStatus.ING.getCode().equals(buildRecord.getStatus())||BuildStatus.FAILUE.getCode().equals(buildRecord.getStatus())){
						buildSnapshotDTO.setStatus(buildRecord.getStatus());
					}
					
					records.add(parseBuildRecord(buildRecord, buildRecord.getHostNames()));
				}
				buildSnapshotDTO.setRecords(records);
				
				if(buildSnapshotDTO.getStatus()==null){
					buildSnapshotDTO.setStatus(buildRecordVo.getData().get(0).getStatus());
				}
			}
			buildSnapshotDTOs.add(buildSnapshotDTO);
		}
		
		return buildSnapshotDTOs;
    	
    }

	/* (non-Javadoc)
	 * @see BuilderService#buildRecords(java.lang.Long, java.lang.Long, java.lang.Long)
	 */
	@Override
	public List<BuildSnapshotDTO> buildRecords(Long projectId, Long appId, String envId) {
		if(projectId!=null){
			return this.queryPlanBuildRecord(projectId, envId);
		}
		
		UserDetailDTO userDTO= SsoHelper.currentUser();
		
		List<BuildSnapshotDTO> buildSnapshotDTOs=new ArrayList<>();

		ResponseVo<List<BuildRecord>> buildRecordVo=deployService.queryBuildListByAppId(appId, envId ,1, 100);
		List<BuildRecord> buildRecordList=buildRecordVo.getData();
		LOGGER.debug("buildRecordList:{}", JSON.toJSONString(buildRecordList));
		if(CollectionUtils.isEmpty(buildRecordList)){
			this.addApprovalRecords(buildSnapshotDTOs, appId, envId);
			return buildSnapshotDTOs;
		}
		
		int i=0;
		for(BuildRecord buildRecord:buildRecordList){
			if(buildRecord.getGroupId()!=0&&!(buildRecord.getGroupId().equals(buildRecord.getBuildId()))){
				//如果分组ID不是0且不是当前ID，说明他是组员，直接PASS
				continue;
			}
			
			if(BuildStatus.PASS.getCode().equals(buildRecord.getStatus())&&
					!userDTO.getNickname().equals(buildRecord.getCreateUser())){
				//如果状态是审核通过，但是不是审核发起人，直接PASS
				continue;
			}
			
			BuildSnapshotDTO buildSnapshotDTO=new BuildSnapshotDTO();
			
			if(i==0){
				buildSnapshotDTO.setEnable(true);
			}
			i++;
			
			buildSnapshotDTO.setBuildId(buildRecord.getBuildId());
			buildSnapshotDTO.setAppId(appId);
			buildSnapshotDTO.setEnv(buildRecord.getEnv());
			buildSnapshotDTO.setBranch(buildRecord.getBranch());
			buildSnapshotDTO.setAppName(buildRecord.getAppName());
			buildSnapshotDTO.setCreatedTime(buildRecord.getCreateTime());
			buildSnapshotDTO.setExecutorName(buildRecord.getCreateUser());
			buildSnapshotDTO.setStatus(buildRecord.getStatus());
			buildSnapshotDTO.setApprovalId(buildRecord.getApprovalId());
			buildSnapshotDTO.setGrayPercent(buildRecord.getGrayPercent());
			buildSnapshotDTO.setSuccess(BuildStatus.SUCCESS.getCode().equals(buildRecord.getStatus()));
			
			if(!BuildStatus.PASS.getCode().equals(buildRecord.getStatus())){
				buildSnapshotDTO.setId(buildRecord.getBuildId());

				List<BuildSnapshotDTO> records=new ArrayList<>();
				
				ResponseVo<List<BuildRecord>> subBuildRecordVo=deployService.queryBuildListByGroupId(buildRecord.getBuildId(), envId);
				List<BuildRecord> subBuildRecordList=subBuildRecordVo.getData();
				if(CollectionUtils.isEmpty(subBuildRecordList)||subBuildRecordList.size()==1){
					String hostNames=buildRecord.getHostNames();
					if(hostNames.contains(",")){
						for(String hostName:hostNames.split(",")){
							records.add(parseBuildRecord(buildRecord, hostName));
						}
					}else{
						records.add(parseBuildRecord(buildRecord, hostNames));
					}
					if(!CollectionUtils.isEmpty(subBuildRecordList)&&"A".equals(subBuildRecordList.get(0).getGroupName())){
						buildSnapshotDTO.setGrayStatus(TaskStatus.A_FINISHED.toString());
					}else{
						buildSnapshotDTO.setGrayStatus(TaskStatus.FINISHED.toString());
					}
				}else{
					int count=0;
					long bBuildId=0;
					for(BuildRecord subBuildRecord:subBuildRecordList){
						String hostNames=subBuildRecord.getHostNames();
						if(hostNames.contains(",")){
							for(String hostName:hostNames.split(",")){
								records.add(parseBuildRecord(subBuildRecord, hostName));
							}
						}else{
							records.add(parseBuildRecord(subBuildRecord, hostNames));
						}
						//如果有一组失败，那么都失败
						if(!BuildStatus.SUCCESS.getCode().equals(subBuildRecord.getStatus())){
							buildSnapshotDTO.setStatus(subBuildRecord.getStatus());
						}
						if(BuildStatus.PASS.getCode().equals(subBuildRecord.getStatus())){
							count++;
							bBuildId=subBuildRecord.getBuildId();
						}
					}
					if(count>0){
						//如果有审批通过的状态，则置为灰度发布完成
						buildSnapshotDTO.setGrayStatus(TaskStatus.A_FINISHED.toString());
						buildSnapshotDTO.setbBuildId(bBuildId);
					}else{
						buildSnapshotDTO.setGrayStatus(TaskStatus.FINISHED.toString());
					}
				}
				buildSnapshotDTO.setRecords(records);
			}
			
			buildSnapshotDTOs.add(buildSnapshotDTO);
		}
		
		this.addApprovalRecords(buildSnapshotDTOs, appId, envId);

		//按创建时间倒序排序
		buildSnapshotDTOs.sort((o1, o2) -> o2.getCreatedTime().compareTo(o1.getCreatedTime()));
		return buildSnapshotDTOs;
	}
	
	/**
	 * 功能描述: <br>
	 * 加入审批的记录
	 *
	 * @param buildSnapshotDTOs
	 * @param appId
	 * @param env
	 */
	private void addApprovalRecords(List<BuildSnapshotDTO> buildSnapshotDTOs, Long appId, String env){
		Page<DeployApproval> page=new Page<>(1, 50);
		DeployApproval deployApprovalParam = new DeployApproval();
		deployApprovalParam.setAppId(appId);
		deployApprovalParam.setEnv(env);
		deployApprovalParam.setCreateId(SsoHelper.currentUser().getId());
		Page<DeployApproval> pageList=deployApprovalService.selectPage(page, deployApprovalParam, " create_time desc");
		List<DeployApproval> deployApprovalList=pageList.getRecords();
		LOGGER.debug("deployApprovalList:{}", JSON.toJSONString(deployApprovalList));

		for(DeployApproval deployApproval:deployApprovalList){
			
			for(BuildSnapshotDTO buildSnapshotDTO:buildSnapshotDTOs){
				if(deployApproval.getGroupId().equals(buildSnapshotDTO.getId())){
					//审批分组ID和构建记录ID相等
					if(EnumDefinition.ApprovalStatus.REFUSE.getCode().equals(deployApproval.getStatus())){
						buildSnapshotDTO.setStatus(6);//6：驳回
					}else if(EnumDefinition.ApprovalStatus.INIT.getCode().equals(deployApproval.getStatus())){
						buildSnapshotDTO.setStatus(5);//5：待审批
					}
					buildSnapshotDTO.setComment(deployApproval.getComment());
					buildSnapshotDTO.setApprovalId(deployApproval.getId());
				}
				
			}
			
			if(!EnumDefinition.ApprovalStatus.AGREE.getCode().equals(deployApproval.getStatus())&&deployApproval.getGroupId()==0){
				BuildSnapshotDTO buildSnapshotDTO=new BuildSnapshotDTO();
				buildSnapshotDTO.setAppId(appId);
				buildSnapshotDTO.setApprovalId(deployApproval.getId());
				buildSnapshotDTO.setBranch(deployApproval.getBranch());
				buildSnapshotDTO.setCreatedTime(deployApproval.getCreateTime());
				buildSnapshotDTO.setExecutorName(deployApproval.getCreateName());
				buildSnapshotDTO.setComment(deployApproval.getComment());
				buildSnapshotDTO.setStatus(EnumDefinition.ApprovalStatus.REFUSE.getCode().equals(deployApproval.getStatus())?6:5);//6：驳回，5：待审批
				buildSnapshotDTOs.add(buildSnapshotDTO);
			}
		}
	}
	
	private BuildSnapshotDTO parseBuildRecord(BuildRecord buildRecord,String hostName){
		BuildSnapshotDTO record=new BuildSnapshotDTO();
		record.setServerHostName(hostName);
		record.setId(buildRecord.getBuildId());
		record.setEnv(buildRecord.getEnv());
		record.setBranch(buildRecord.getBranch());
		record.setAppName(buildRecord.getAppName());
		record.setGroupName(StringUtils.isEmpty(buildRecord.getGroupName())?null:buildRecord.getGroupName());
		record.setGroupId(buildRecord.getGroupId()==0?null:buildRecord.getGroupId());
		record.setStatus(buildRecord.getStatus());
		record.setSuccess(BuildStatus.SUCCESS.getCode().equals(buildRecord.getStatus()));
		if(buildRecord.getPackageCmd()==1&&buildRecord.getDeployCmd()==1&&buildRecord.getTestCmd()==1){
			record.setStep(7);//打包-部署-测试
		}else if(buildRecord.getPackageCmd()==1&&buildRecord.getDeployCmd()==1&&buildRecord.getTestCmd()==0){
			record.setStep(3);//打包-部署
		}else if(buildRecord.getPackageCmd()==1&&buildRecord.getDeployCmd()==0&&buildRecord.getTestCmd()==1){
			record.setStep(5);//打包-测试
		}else if(buildRecord.getPackageCmd()==0&&buildRecord.getDeployCmd()==1&&buildRecord.getTestCmd()==1){
			record.setStep(6);//部署-测试
		}else if(buildRecord.getPackageCmd()==1&&buildRecord.getDeployCmd()==0&&buildRecord.getTestCmd()==0){
			record.setStep(1);//打包
		}else if(buildRecord.getPackageCmd()==0&&buildRecord.getDeployCmd()==1&&buildRecord.getTestCmd()==0){
			record.setStep(2);//部署
		}else if(buildRecord.getPackageCmd()==0&&buildRecord.getDeployCmd()==0&&buildRecord.getTestCmd()==1){
			record.setStep(4);//测试
		}
		record.setDeploymentId(buildRecord.getBuildNo());
		return record;
	}

	/* (non-Javadoc)
	 * @see BuilderService#execSingleTask(SingleTaskDTO)
	 */
	@Override
	public CommandContext execSingleTask(SingleTaskDTO taskDTO) {
		CommandContext commandContext=new CommandContext();

		BuildParam buildParam=new BuildParam();
		buildParam.setBuildId(taskDTO.getId());
		buildParam.setAppId(taskDTO.getAppId());
		buildParam.setBranchName(taskDTO.getGitBranch());
		UserDetailDTO userDTO=SsoHelper.currentUser();
		buildParam.setBuildUserName(userDTO.getNickname());
		buildParam.setEnvName(taskDTO.getEnv());
		buildParam.setGroupName(taskDTO.getGroupName());
		buildParam.setK8s(taskDTO.isK8s());
		ResponseVo<Long> result=deployService.build(buildParam);
		//回滚暂不考虑
		
		if(result.isSuccess()){
			commandContext.setCreated(true);
			commandContext.setBuildParentSnapshotId(result.getData());
			commandContext.setTaskCount(1);
			commandContext.setTaskIds(new ArrayList<>());
		}else{
			commandContext.setCreated(false);
			commandContext.setMessage(result.getMsg());;
			LOGGER.error("构建失败："+result.getMsg());
		}
		return commandContext;
	}
	
	@Override
    public CommandContext execBGroup(Long groupId,String envName,Long bBuildId) {
		ResponseVo<List<BuildRecord>> subBuildRecordVo=deployService.queryBuildListByGroupId(groupId, envName);
        List<BuildRecord> buildRecordList=subBuildRecordVo.getData();
		if (!subBuildRecordVo.isSuccess()||CollectionUtils.isEmpty(buildRecordList)) {
            throw new BizMessageException("无效的发布记录ID");
        }
        
        boolean flag=true;
        for(BuildRecord buildRecord:buildRecordList){
        	if(!BuildStatus.SUCCESS.getCode().equals(buildRecord.getStatus())
        			&&!BuildStatus.PASS.getCode().equals(buildRecord.getStatus())){
        		flag=false;
        		break;
        	}
        }
        
        //A组失败了则不让继续
        if(!flag){
        	throw new BizMessageException("灰度执行没有成功");
        }
        
        CommandContext commandContext=new CommandContext();

		BuildParam buildParam=new BuildParam();
		BuildRecord buildRecord=buildRecordList.get(0);
		buildParam.setBuildId(bBuildId);
		buildParam.setAppId(buildRecord.getAppId());
		buildParam.setBranchName(buildRecord.getBranch());
		UserDetailDTO userDTO=SsoHelper.currentUser();
		buildParam.setBuildUserName(userDTO.getNickname());
		buildParam.setEnvName(buildRecord.getEnv());
		//B组将pakage设置为false
		buildParam.setPackage(false);
		buildParam.setGroupName("B");
		buildParam.setGroupId(groupId);
		ResponseVo<Long> result=deployService.build(buildParam);
        
		if(result.isSuccess()){
			commandContext.setCreated(true);
			commandContext.setBuildParentSnapshotId(result.getData());
			commandContext.setTaskCount(1);
			commandContext.setTaskIds(new ArrayList<Long>());
			commandContext.setMessage(buildRecord.getAppName());
			commandContext.setAppId(buildRecord.getAppId());
		}else{
			commandContext.setCreated(false);
			commandContext.setMessage(result.getMsg());;
			LOGGER.error("构建失败："+result.getMsg());
		}
		return commandContext;
    }

	/* (non-Javadoc)
	 * @see BuilderService#execPublishProject(ProjectTaskDTO)
	 */
	@Override
	@Transactional
	public BatchBuildResult execPublishProject(ProjectTaskDTO param) {
		UserDetailDTO userDTO=SsoHelper.currentUser();

		Date nowDate=new Date();
		DeployPlanRecord deployPlanRecord=new DeployPlanRecord();
		deployPlanRecord.setCreateName(userDTO.getNickname());
		deployPlanRecord.setCreateTime(nowDate);
		deployPlanRecord.setPlanId(param.getProjectId());
		//批量发布记录
		deployPlanRecordService.insertSelective(deployPlanRecord);
		
		//测试记录
		DeployPlanTest deployPlanTestParam=new DeployPlanTest();
		deployPlanTestParam.setPlanId(param.getProjectId());
		DeployPlanTest deployPlanTestRes=deployPlanTestService.selectOne(deployPlanTestParam);
		if(deployPlanTestRes!=null){
			//更新
			DeployPlanTest deployPlanTestUp=new DeployPlanTest();
			deployPlanTestUp.setId(deployPlanTestRes.getId());
			deployPlanTestUp.setStatus(EnumDefinition.TestStatus.INIT.getCode());
			deployPlanTestService.updateSelectiveById(deployPlanTestUp);
		}else{
			//插入
			DeployPlanTest deployPlanTest=new DeployPlanTest();
			deployPlanTest.setPlanId(param.getProjectId());
			deployPlanTest.setStatus(EnumDefinition.TestStatus.INIT.getCode());
			deployPlanTest.setUpdateTime(nowDate);
			deployPlanTestService.insertSelective(deployPlanTest);
		}
		
		DeployPlan deployPlanUp=new DeployPlan();
		deployPlanUp.setId(param.getProjectId());
		deployPlanUp.setExecuteTime(nowDate);
		deployPlanUp.setExecuteName(userDTO.getNickname());
		//更新执行人
		deployPlanService.updateSelectiveById(deployPlanUp);
		
		List<Long> appIdList=param.getAppIds();
		
		List<BuildParam> buildParamList=new ArrayList<BuildParam>();
		for(Long appId:appIdList){
			ProjectApp projectAppParam=new ProjectApp();
			projectAppParam.setAppId(appId);
			projectAppParam.setProjectId(param.getProjectId());
			ProjectApp projectApp=projectAppService.selectOne(projectAppParam);
			
			BuildParam buildParam=new BuildParam();
			buildParam.setAppId(appId);
			buildParam.setBranchName(projectApp.getAppBranch());
			buildParam.setBuildUserName(userDTO.getNickname());
			buildParam.setEnvName("sit");//固定为sit环境
			buildParam.setTest(true);
			
			buildParamList.add(buildParam);
		}
		
		BatchBuildParam batchBuildParam=new BatchBuildParam();
		batchBuildParam.setBuildParams((BuildParam[])buildParamList.toArray(new BuildParam[0]));
		batchBuildParam.setBatchId(deployPlanRecord.getId());
		ResponseVo<BatchBuildResult> result=deployService.buildBatch(batchBuildParam);
		
		if(!result.isSuccess()){
			throw new RuntimeException(result.getMsg());
		}
		
		return result.getData();
	}
	
}
